﻿//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
#include "study03.h"
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本

/*
static 关键字:
	在 C/C++ 中，static 关键字用来声明静态变量和静态函数。可以把栈区的变量和函数声明为静态的，
	静态变量一般存放在静态存储区，静态区变量的生命周期从程序开始到结束，直到程序结束。

C++ 中结构体或者类中的静态变量与静态函数：
	静态变量语法：
		static 数据类型 变量名;
		静态变量：在整个程序运行期间，只存在一份副本，所有对象都可以访问，其他文件无法访问。
		静态变量的作用域：全局作用域、文件作用域、函数作用域。
		静态变量的生命周期：程序运行期间，直到程序结束。
	可以将结构体（或类）内的静态变量生命周期变长，语法为：
		数据类型 结构体或类名::变量名;
		这就使得结构体内的静态变量成为了静态全局变量。
		调用方式：
			结构体名::变量名 = 值;
	静态函数语法：
		static 返回类型 函数名(形式参数列表) { 函数体 }
	结构体内的静态函数本来就是全局的，可以直接调用，调用语法：
		结构体名::函数名(实际参数列表);

	在 C++ 结构体或类中，静态成员只能访问静态成员，不能访问非静态成员，而非静态成员可以访问静态成员；
		静态成员只能有一个，不管是否定义多个结构体或类，都只会有一个同名的静态成员变量；
		所以结构体或类的静态成员变量在同类型名的结构体中是共享的。

*/

static int v1 = 10; // 静态变量，当前文件的全局作用域，当前文件所有函数都可以访问，其他文件无法访问

static void func1()
{
	// 静态函数，当前文件的全局作用域，当前文件所有函数都可以访问，其他文件无法访问
	v1 += 20;
	std::cout << "static: v1 = " << v1 << ";  ";
	static int v2 = 0;
	// 静态局部变量，当前函数作用域，当前函数内所有语句都可以访问，其他函数无法访问
	// 而且 static 修饰局部变量，函数退出后，局部变量不会被销毁，下次进入函数时，仍然闹存之前的值
	v2 += 10;
	std::cout << "func1: v2 = " << v2 << ";  ";
	int v3 = 0; // 局部变量，当前函数作用域，退出函数销毁，再次进入函数时，变量不存在，重新初始化
	v3 += 50;
	std::cout << "func1: v3 = " << v3 << std::endl;
}

typedef struct StaticStruct { // C++ 的结构体，也相当于类
	static int x, y; // 静态成员变量，类似于函数中的静态变量，注意 C 中没有静态成员变量
	int a, b; // 非静态成员变量
	static void show_values() {
		std::cout << "StaticStruct: x = " << x << ", y = " << y << std::endl;
		//cout << "StaticStruct: a = " << a << ", b = " << b << endl; // err
	}
	void print_values() {
		std::cout << "x = " << x << ", y = " << y << std::endl;  // ok
		std::cout << "a = " << a << ", b = " << a << std::endl;
	}
} ss;

int ss::x; // C++ 结构体静态成员变量声明，
// 相当于 StaticStruct 中的静态变量 x 成为了静态全局变量
int ss::y;

class SingleStatic { // C++ 的类
	/*private:
		static SingleStatic* singleton; // 静态成员变量，类似于函数中的静态变量

	public:
		static string name; // 静态成员变量
		static SingleStatic& GetInstance() { // 引用类，返回单例对象
			return *singleton;	} // 静态成员函数，返回单例对象 */

//简化上述代码：
public:
	static std::string name; // 静态成员变量
	static SingleStatic& GetInstance()
	{ // 引用类，返回单例对象
		static SingleStatic singleton; // 静态成员变量，类似于函数中的静态变量
		return singleton; // 静态成员函数，返回单例对象
	}

	void print_name() {
		//this->name = name;
		std::cout << "SingleStatic: name = " << name << std::endl;
	}
};

std::string SingleStatic::name;
//SingleStatic* SingleStatic::singleton = nullptr;//初始化，注意这里不能用 new 关键字

void test_static()
{ // 非静态函数，当前文件的全局作用域，当前文件所有函数都可以访问，其他文件无法访问
	print_start("C++ 中简单了解结构体和类中的静态 static 关键字部分");
	int i = 0;
	for (i = 1; i <= 5; i++)
	{
		std::cout << "in test_static i = " << i << std::endl;
		func1();
	}

	ss::x = 100; // 访问静态成员变量，并初始化或修改值
	ss::y = 200;
	ss::show_values(); // 调用 C++ 结构体静态成员函数

	ss::x = 300; // 修改静态成员变量的值
	ss::y = 400;
	ss::show_values(); // 调用 C++ 结构体静态成员函数

	ss s1;
	s1.x = 0;
	s1.y = 0;
	s1.a = 0;
	s1.b = 0;
	for (i = 1; i <= 5; i++)
	{
		s1.x += 1;
		s1.y += 10;
		s1.a += 1;
		s1.b += 10;
		s1.print_values();
	}

	ss s2;
	s2.x = 1000;
	s2.y = 2000;
	s2.a = 1000;
	s2.b = 2000;
	s2.print_values();
	s1.print_values(); // 静态成员只能有一个，不管是否定义多个结构体，都只会有一个同名的静态成员变量
	ss::show_values(); // 可以看到这里的静态成员变量 x 和 y 也被修改了

	SingleStatic::name = "single";
	SingleStatic::GetInstance().print_name(); // 调用类静态成员函数，返回单例对象

	print_end("C++ 中简单了解结构体和类中的静态 static 关键字部分");
}
